from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from sqlalchemy import func
from app.api.deps import get_db, get_current_user
from app.models.user import User
from app.models.category import Category
from app.models.document import Document
from app.schemas.category import (
    CategoryCreate,
    CategoryUpdate,
    CategoryResponse,
    CategoryListResponse
)
from typing import List, Optional
import logging
import uuid

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/categories", tags=["categories"])


def build_category_tree(categories: List[Category], parent_id: Optional[str] = None) -> List[dict]:
    """构建分类树"""
    tree = []
    for cat in categories:
        if cat.parent_id == parent_id:
            cat_dict = {
                "id": cat.id,
                "name": cat.name,
                "description": cat.description,
                "icon": cat.icon,
                "color": cat.color,
                "parent_id": cat.parent_id,
                "sort_order": cat.sort_order,
                "created_by": cat.created_by,
                "created_at": cat.created_at,
                "updated_at": cat.updated_at,
                "document_count": 0,  # 后续添加统计
                "children": build_category_tree(categories, cat.id)
            }
            tree.append(cat_dict)
    return sorted(tree, key=lambda x: x['sort_order'])


@router.get("/list", response_model=CategoryListResponse)
async def list_categories(
    tree: bool = False,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """
    获取分类列表
    
    Args:
        tree: 是否返回树形结构
        current_user: 当前用户
        db: 数据库会话
        
    Returns:
        CategoryListResponse: 分类列表
    """
    try:
        # 获取所有分类
        categories = db.query(Category).order_by(Category.sort_order, Category.created_at).all()
        
        # 统计每个分类的文档数量
        doc_counts = db.query(
            Document.category_id,
            func.count(Document.id).label('count')
        ).filter(
            Document.category_id.isnot(None)
        ).group_by(Document.category_id).all()
        
        doc_count_map = {cat_id: count for cat_id, count in doc_counts}
        
        if tree:
            # 返回树形结构
            tree_data = build_category_tree(categories)
            
            # 递归添加文档数量
            def add_doc_counts(nodes):
                for node in nodes:
                    node['document_count'] = doc_count_map.get(node['id'], 0)
                    if node['children']:
                        add_doc_counts(node['children'])
            
            add_doc_counts(tree_data)
            
            return {
                "items": tree_data,
                "total": len(categories)
            }
        else:
            # 返回平铺列表
            items = []
            for cat in categories:
                cat_dict = {
                    "id": cat.id,
                    "name": cat.name,
                    "description": cat.description,
                    "icon": cat.icon,
                    "color": cat.color,
                    "parent_id": cat.parent_id,
                    "sort_order": cat.sort_order,
                    "created_by": cat.created_by,
                    "created_at": cat.created_at,
                    "updated_at": cat.updated_at,
                    "document_count": doc_count_map.get(cat.id, 0),
                    "children": []
                }
                items.append(cat_dict)
            
            return {
                "items": items,
                "total": len(categories)
            }
        
    except Exception as e:
        logger.error(f"获取分类列表失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"获取分类列表失败: {str(e)}")


@router.post("/create", response_model=CategoryResponse)
async def create_category(
    category: CategoryCreate,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """
    创建分类
    
    Args:
        category: 分类数据
        current_user: 当前用户
        db: 数据库会话
        
    Returns:
        CategoryResponse: 创建的分类
    """
    try:
        # 检查分类名称是否已存在
        existing = db.query(Category).filter(Category.name == category.name).first()
        if existing:
            raise HTTPException(status_code=400, detail="分类名称已存在")
        
        # 如果有父分类，检查是否存在
        if category.parent_id:
            parent = db.query(Category).filter(Category.id == category.parent_id).first()
            if not parent:
                raise HTTPException(status_code=404, detail="父分类不存在")
        
        # 创建分类
        new_category = Category(
            id=str(uuid.uuid4()),
            name=category.name,
            description=category.description,
            icon=category.icon,
            color=category.color,
            parent_id=category.parent_id,
            sort_order=category.sort_order,
            created_by=str(current_user.id)
        )
        
        db.add(new_category)
        db.commit()
        db.refresh(new_category)
        
        logger.info(f"用户 {current_user.username} 创建分类: {new_category.name}")
        
        return {
            "id": new_category.id,
            "name": new_category.name,
            "description": new_category.description,
            "icon": new_category.icon,
            "color": new_category.color,
            "parent_id": new_category.parent_id,
            "sort_order": new_category.sort_order,
            "created_by": new_category.created_by,
            "created_at": new_category.created_at,
            "updated_at": new_category.updated_at,
            "document_count": 0,
            "children": []
        }
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"创建分类失败: {str(e)}")
        db.rollback()
        raise HTTPException(status_code=500, detail=f"创建失败: {str(e)}")


@router.get("/{category_id}", response_model=CategoryResponse)
async def get_category(
    category_id: str,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """
    获取分类详情
    
    Args:
        category_id: 分类ID
        current_user: 当前用户
        db: 数据库会话
        
    Returns:
        CategoryResponse: 分类信息
    """
    category = db.query(Category).filter(Category.id == category_id).first()
    
    if not category:
        raise HTTPException(status_code=404, detail="分类不存在")
    
    # 统计文档数量
    doc_count = db.query(func.count(Document.id)).filter(
        Document.category_id == category_id
    ).scalar() or 0
    
    return {
        "id": category.id,
        "name": category.name,
        "description": category.description,
        "icon": category.icon,
        "color": category.color,
        "parent_id": category.parent_id,
        "sort_order": category.sort_order,
        "created_by": category.created_by,
        "created_at": category.created_at,
        "updated_at": category.updated_at,
        "document_count": doc_count,
        "children": []
    }


@router.put("/{category_id}", response_model=CategoryResponse)
async def update_category(
    category_id: str,
    category_update: CategoryUpdate,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """
    更新分类
    
    Args:
        category_id: 分类ID
        category_update: 更新数据
        current_user: 当前用户
        db: 数据库会话
        
    Returns:
        CategoryResponse: 更新后的分类
    """
    category = db.query(Category).filter(Category.id == category_id).first()
    
    if not category:
        raise HTTPException(status_code=404, detail="分类不存在")
    
    try:
        # 检查名称是否重复
        if category_update.name and category_update.name != category.name:
            existing = db.query(Category).filter(
                Category.name == category_update.name,
                Category.id != category_id
            ).first()
            if existing:
                raise HTTPException(status_code=400, detail="分类名称已存在")
        
        # 更新字段
        if category_update.name is not None:
            category.name = category_update.name
        if category_update.description is not None:
            category.description = category_update.description
        if category_update.icon is not None:
            category.icon = category_update.icon
        if category_update.color is not None:
            category.color = category_update.color
        if category_update.parent_id is not None:
            # 不能将自己设为父分类
            if category_update.parent_id == category_id:
                raise HTTPException(status_code=400, detail="不能将自己设为父分类")
            category.parent_id = category_update.parent_id
        if category_update.sort_order is not None:
            category.sort_order = category_update.sort_order
        
        db.commit()
        db.refresh(category)
        
        logger.info(f"用户 {current_user.username} 更新分类: {category.name}")
        
        # 统计文档数量
        doc_count = db.query(func.count(Document.id)).filter(
            Document.category_id == category_id
        ).scalar() or 0
        
        return {
            "id": category.id,
            "name": category.name,
            "description": category.description,
            "icon": category.icon,
            "color": category.color,
            "parent_id": category.parent_id,
            "sort_order": category.sort_order,
            "created_by": category.created_by,
            "created_at": category.created_at,
            "updated_at": category.updated_at,
            "document_count": doc_count,
            "children": []
        }
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"更新分类失败: {str(e)}")
        db.rollback()
        raise HTTPException(status_code=500, detail=f"更新失败: {str(e)}")


@router.delete("/{category_id}")
async def delete_category(
    category_id: str,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """
    删除分类
    
    Args:
        category_id: 分类ID
        current_user: 当前用户
        db: 数据库会话
        
    Returns:
        dict: 删除结果
    """
    category = db.query(Category).filter(Category.id == category_id).first()
    
    if not category:
        raise HTTPException(status_code=404, detail="分类不存在")
    
    try:
        # 检查是否有子分类
        children = db.query(Category).filter(Category.parent_id == category_id).count()
        if children > 0:
            raise HTTPException(status_code=400, detail="该分类下还有子分类，无法删除")
        
        # 检查是否有文档
        doc_count = db.query(func.count(Document.id)).filter(
            Document.category_id == category_id
        ).scalar()
        
        if doc_count > 0:
            raise HTTPException(status_code=400, detail=f"该分类下还有{doc_count}个文档，无法删除")
        
        # 删除分类
        db.delete(category)
        db.commit()
        
        logger.info(f"用户 {current_user.username} 删除分类: {category.name}")
        
        return {"message": "删除成功"}
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"删除分类失败: {str(e)}")
        db.rollback()
        raise HTTPException(status_code=500, detail=f"删除失败: {str(e)}")

